package com.cdks.wuxiu.api.controller;

import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;

import com.alipay.api.AlipayApiException;
import com.alipay.api.internal.util.AlipaySignature;
import com.cdks.wuxiu.api.component.annotation.ThirdParty;
import com.cdks.wuxiu.api.component.constant.Constant;
import com.cdks.wuxiu.api.model.param.PaymentApplepayParam;
import com.cdks.wuxiu.api.service.MessageService;
import com.cdks.wuxiu.api.service.RechargeService;
import com.cdks.wuxiu.api.util.ApplepayUtils;
import com.cdks.wuxiu.api.util.HttpUtils;
import com.cdks.wuxiu.api.util.SmsUtils;
import com.cdks.wuxiu.common.config.AlipayProps;
import com.cdks.wuxiu.common.config.WxpayProps;
import com.cdks.wuxiu.common.model.api.ApiResult;
import com.cdks.wuxiu.entity.message.ChatPrivateData;
import com.cdks.wuxiu.entity.mysql.RechargeOrderInfo;
import com.ijpay.alipay.AliPayApi;
import com.ijpay.core.enums.SignType;
import com.ijpay.core.kit.HttpKit;
import com.ijpay.core.kit.WxPayKit;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;

import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import springfox.documentation.annotations.ApiIgnore;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.HashMap;
import java.util.Map;


@Slf4j
@Api(tags = "支付")
@ApiIgnore
@RestController
@RequestMapping("/payment")
public class PaymentController {
    @Resource
    private RechargeService rechargeService;
    @Resource
    private MessageService messageService;

    
    private int sendMessage(long userId, BigDecimal cost)
    {
        //事件回调
        ThreadUtil.execAsync(() -> {            
            JSONObject json  = new JSONObject();
            json.set("userId", userId);
            json.set("money", cost);
            HttpUtils.send_post_request("http://localhost:8183/callback/userPayment.php", null, JSONUtil.toJsonStr(json));
        });

        ChatPrivateData data  = new ChatPrivateData();
        data.setContent("尊敬的用户，您充值的" + cost + "元已到账，请前往“我的钱包”查看。");
        messageService.sendSystemMessage(userId, Constant.MSG_TYPE_TEXT, data);

        return 0;
    }

    @ThirdParty
    @ApiOperation("支付宝通知")
    @RequestMapping("/alipay")
    public String alipay(HttpServletRequest request) {
        Map<String, String> params = AliPayApi.toMap(request);
        log.info("支付宝异步通知:" + params);

        //订单支付失败直接返回
        if (!params.get("trade_status").equals("TRADE_SUCCESS"))
        {
            log.error("支付宝支付失败");

            return "failure";
        }

        // 校验签名
        boolean verifyResult = false;
        try {
            verifyResult = AlipaySignature.rsaCheckV1(params, AlipayProps.publicKey, "UTF-8", "RSA2");
        } catch (AlipayApiException e) {
            //发送管理通知
            SmsUtils.sendManageNotice("支付宝通知处理失败");

            log.error("支付宝通知处理失败", e);

            return "failure";
        }

        if (!verifyResult)
        {
            //发送管理通知
            SmsUtils.sendManageNotice("支付宝验签失败");

            log.error("支付宝验签失败");

            return "failure";
        }

        // 支付金额
        BigDecimal payAmount  = new BigDecimal(params.get("buyer_pay_amount"));
        // 商户订单号
        String orderNo  = params.get("out_trade_no");

        RechargeOrderInfo order  = rechargeService.getOrderByOrderNo(orderNo);
        if (payAmount.compareTo(order.getMoney()) != 0)
        {
            //发送管理通知
            SmsUtils.sendManageNotice("支付宝订单错误");

            log.error("支付宝订单错误");

            return "failure";
        }        

        // 支付宝交易凭证号
        order.setStatus(Constant.PAY_STATUS_PAYED);
        order.setThirdNo(params.get("trade_no"));
        int ret  = rechargeService.payOrderSuccess(order);
        if (ret < 0)
        {
            //发送管理通知
            SmsUtils.sendManageNotice("支付宝更新订单失败");

            log.error("支付宝更新订单失败：" + order);

            return "failure";
        }

        //发送管理通知
        SmsUtils.sendManageNotice("用户" + order.getUserId() + "通过支付宝成功充值" + order.getMoney() + "元");
        //推送通知
        sendMessage(order.getUserId(), order.getMoney());

        return "success";
    }

    @ThirdParty
    @ApiOperation("微信支付通知")
    @RequestMapping("/wxpay")
    public String wxpay(HttpServletRequest request) {
        String xmlMsg = HttpKit.readData(request);
        Map<String, String> params = WxPayKit.xmlToMap(xmlMsg);
        log.info("微信支付异步通知" + params);

        //订单支付失败直接返回
        if ((!WxPayKit.codeIsOk(params.get("return_code"))) || (!WxPayKit.codeIsOk(params.get("result_code"))))
        {
            log.error("微信支付失败");

            return null;
        }

        boolean verifyResult  = WxPayKit.verifyNotify(params, WxpayProps.appSecret, SignType.MD5);
        // 校验签名
        if (!verifyResult)
        {
            //发送管理通知
            SmsUtils.sendManageNotice("微信验签失败");

            log.error("微信验签失败");

            return null;
        }

        // 支付金额
        BigDecimal payAmount  = new BigDecimal(params.get("total_fee")).divide(new BigDecimal("100"), 2, RoundingMode.HALF_UP);
        // 商户订单号
        String orderNo = params.get("out_trade_no");

        RechargeOrderInfo order  = rechargeService.getOrderByOrderNo(orderNo);
        if (payAmount.compareTo(order.getMoney()) != 0)
        {
            log.error("微信订单错误");

            return null;
        }        

        // 微信支付订单号
        order.setStatus(Constant.PAY_STATUS_PAYED);
        order.setThirdNo(params.get("transaction_id"));
        int ret  = rechargeService.payOrderSuccess(order);
        if (ret < 0)
        {
            //发送管理通知
            SmsUtils.sendManageNotice("微信支付更新订单失败");

            log.error("微信支付更新订单失败：" + order);

            return null;
        }

        //发送管理通知
        SmsUtils.sendManageNotice("用户" + order.getUserId() + "通过微信成功充值" + order.getMoney() + "元");
        //推送通知
        sendMessage(order.getUserId(), order.getMoney());

        // 成功处理返回 xml
        Map<String, String> xml = new HashMap<>(2);
        xml.put("return_code", "SUCCESS");
        xml.put("return_msg", "OK");
        String success = WxPayKit.toXml(xml);

        return success;
    }

    @ApiOperation("苹果支付收据验证")
    @PostMapping("/applepay")
    public ApiResult<Object> applepay(@RequestBody @Valid PaymentApplepayParam param) {
        JSONObject result = ApplepayUtils.verifyReceipt(param.getReceipt(), false);
        String status = result.getStr("status");
        // 21007 沙箱环境
        if ("21007".equals(status)) {
            result = ApplepayUtils.verifyReceipt(param.getReceipt(), true);
            status = result.getStr("status");
        }
        
        // 成功
        if (!"0".equals(status))
        {
            log.error("苹果支付验证票据失败：param = " + param + ", result = " + result);

            return ApiResult.failed(10, "支付失败");
        }
        
        JSONArray inApp  = result.getJSONObject("receipt").getJSONArray("in_app");
        for (Object object : inApp)
        {
            RechargeOrderInfo order;
            JSONObject appleOrder  = (JSONObject) object;
            
            if (!appleOrder.getStr("in_app_ownership_type").equals("PURCHASED"))
            {
                //发送管理通知
                SmsUtils.sendManageNotice("苹果支付订单状态异常");

                log.error("苹果支付订单状态异常：param = " + param + ", result = " + result + ", order = " + appleOrder);

                continue;
            }

            //根据苹果订单号查找订单。找到订单则说明是已处理过的订单，不做处理；未找到则说明未处理
            order  = rechargeService.getOrderByThirdNo(appleOrder.getStr("transaction_id"));
            if (order != null)
            {
                if (order.getOrderNo().equals(param.getOrderNo()))
                {
                    log.info("苹果支付已支付：param = " + param + ", result = " + result + ", order = " + order);
                }
                else
                {
                    log.info("苹果支付订单不一致1：param = " + param + ", result = " + result + ", order = " + order);
                }

                continue;
            }

            if (param.getOrderNo() == null)
            {
                //根据product_id查找未支付订单
                order  = rechargeService.getOrderByPriceIdWithStatus(appleOrder.getStr("product_id"), Constant.PAY_STATUS_NOPAY);
                if (order == null)
                {
                    //发送管理通知
                    SmsUtils.sendManageNotice("苹果支付查找订单失败-1");

                    log.error("苹果支付查找订单失败-1：param = " + param + ", result = " + result + ", order = " + appleOrder);

                    continue;
                }
            }
            else
            {
                //根据舞秀订单号查找未支付订单
                order  = rechargeService.getOrderByOrderNoWithStatus(param.getOrderNo(), Constant.PAY_STATUS_NOPAY);
                if (order == null)
                {
                    //发送管理通知
                    SmsUtils.sendManageNotice("苹果支付查找订单失败-2");

                    log.error("苹果支付查找订单失败-2：param = " + param + ", result = " + result + ", order = " + appleOrder);

                    continue;
                }
                else
                {
                    if (Integer.parseInt(appleOrder.getStr("product_id")) != order.getPriceId())
                    {
                        log.info("苹果支付订单不一致2：param = " + param + ", result = " + result + ", order = " + order);

                        continue;
                    }
                }
            }

            //更新订单并增加心豆
            order.setStatus(Constant.PAY_STATUS_PAYED);
            order.setThirdNo(appleOrder.getStr("transaction_id"));
            int ret  = rechargeService.payOrderSuccess(order);
            if (ret == 0)
            {
                log.info("苹果支付成功：param = " + param + ", result = " + result + ", order = " + order);
            }
            else
            {
                //发送管理通知
                SmsUtils.sendManageNotice("苹果支付更新订单失败");

                log.error("苹果支付更新订单失败：param = " + param + ", result = " + result + ", order = " + appleOrder + ", ret = " + ret);

                continue;
            }

            //发送管理通知
            SmsUtils.sendManageNotice("用户" + order.getUserId() + "通过苹果支付成功充值" + order.getMoney() + "元");            
            //推送通知
            sendMessage(order.getUserId(), order.getMoney());
        }

        return ApiResult.success();
    }
}
